//
//  BTDataManager.swift
//  TimeBoat
//
//  Created by Jun on 2022/9/7.
//  Copyright © 2022 Time Boat. All rights reserved.
//

import Foundation
import CoreBluetooth

@objc class BTLEBaseDataManager: NSObject, BTLEManagerDelegate {
    @objc static let shared = BTLEBaseDataManager()
    private let tag = LogTag.init(rawValue: "BTLEBaseDataManager")
    
    private let gattServiceUUID = "18E0";
    private let writeCharacteristicUUID = "2AE0";
    private let notifyCharacteristicUUID = "2AE1";
    private let readCharacteristicUUID = "2AE2";
    
    private var mCBPeripheral: CBPeripheral?
    private var mWriteCharacteristic: CBCharacteristic?
    private var mNotifyCharacteristic: CBCharacteristic?
    private var mReadCharacteristic: CBCharacteristic?
    
    override init() {
        super.init()
    }
    
    func start() {
        BTLEManager.shared.delegate = self
    }
    
    private func getSearchNameList() -> [String] {
        return ConfigManager.shared.getSupportBLENameList()
    }
    
    func discoverPeripheralValid(_ peripheral: CBPeripheral) -> Bool {
        var name = peripheral.name
        if nil == name {
            name = ""
        }
        
        Log.debug(tag: tag, "name = " + name!)
        
        var valid = false
        if name!.count > 0 {
            valid = getSearchNameList().contains(name!)
        }
        
        return valid
    }
    
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        mCBPeripheral = peripheral
    }
    
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral) {
        mCBPeripheral = nil
        mWriteCharacteristic = nil
        mNotifyCharacteristic = nil
        mReadCharacteristic = nil
    }
    
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral) {
        mCBPeripheral = nil
        mWriteCharacteristic = nil
        mNotifyCharacteristic = nil
        mReadCharacteristic = nil
    }
    
    func peripheral(_ peripheral: CBPeripheral, serviceValid service: CBService) -> Bool {
        Log.debug(tag: tag, "service uuid = " + service.uuid.uuidString)
        
        if service.uuid.uuidString.caseInsensitiveCompare(gattServiceUUID) == .orderedSame {
            return true
        }
        
        return false
    }
    
    func peripheral(_ peripheral: CBPeripheral, characteristicNotify characteristic: CBCharacteristic) -> Bool {
        Log.debug(tag: tag, "characteristic uuid = " + characteristic.uuid.uuidString)
        
        var isNotify = false
        if characteristic.uuid.uuidString.caseInsensitiveCompare(writeCharacteristicUUID) == .orderedSame {
            mWriteCharacteristic = characteristic
        } else if characteristic.uuid.uuidString.caseInsensitiveCompare(readCharacteristicUUID) == .orderedSame {
            mReadCharacteristic = characteristic
        } else if characteristic.uuid.uuidString.caseInsensitiveCompare(notifyCharacteristicUUID) == .orderedSame {
            mNotifyCharacteristic = characteristic
            isNotify = true
        }
        
        return isNotify
    }
    
    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic) {
        if nil != characteristic.value {
            let data = characteristic.value!
            let buffer = data.map { $0 }
            let len = buffer.count
            if (len > 0) {
                Log.debug(tag: tag, "write value = " + String.toHexStr(buf: buffer))
            }
        }
    }
    
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic) {
        if (nil != characteristic.value) {
            let data = characteristic.value!
            let buffer = data.map { $0 }
            let len = buffer.count
            if (len > 0) {
                Log.debug(tag: tag, "receive command = " + String.toHexStr(buf: buffer))
                
                BTLEReceiveDataManager.shared.parseCmd(buf: buffer)
            }
        }
    }
    
    @objc func sendCommandData(data: Data) {
        if (nil != mCBPeripheral && nil != mWriteCharacteristic) {
            mCBPeripheral!.writeValue(data, for: mWriteCharacteristic!, type: .withResponse)
        }
    }
    
    @objc func sendCommandBuffer(buffer: [UInt8]) {
        if nil != mCBPeripheral && nil != mWriteCharacteristic {
            Log.debug(tag: tag, "send command = " + String.toHexStr(buf: buffer))
            
            let data = Data.init(bytes: buffer, count: buffer.count)
            
            sendCommandData(data: data)
        } else {
            Log.debug(tag: tag, "peripheral or charactistic is nil")
        }
    }
    
    @objc func readCommand() {
        if nil != mCBPeripheral && nil != mReadCharacteristic {
            mCBPeripheral!.readValue(for: mReadCharacteristic!)
        }
    }
}
